
#include "member_BCube.h"

using namespace BWE;

member_BCube::member_BCube(BCube* cube)
{
	boss = cube;
	length = 1;
	width = 1;
	height = 1;
	lengthSegments = 1;
	widthSegments = 1;
	heightSegments = 1;
	rebuild();
}
member_BCube::~member_BCube()
{

}

void member_BCube::rebuild()
{
	int columnCount = (lengthSegments + widthSegments) * 2 + 1;
	int flankNumVerts = columnCount * (heightSegments + 1);
	int bottomNumVerts = (widthSegments + 1) * (lengthSegments + 1);
	int topNumVerts = bottomNumVerts;
	int totalNumVerts = flankNumVerts + bottomNumVerts + topNumVerts;

	BVectorArray* vertices = boss->vertices();
	BVectorArray* normals = boss->normals();
	BCoordArray* texCoords = boss->texCoords();
	if (!vertices || vertices->size() != totalNumVerts)
	{
		vertices = new BVectorArray(totalNumVerts);
		normals = new BVectorArray(totalNumVerts);
		texCoords = new BCoordArray(totalNumVerts);
		boss->setVertices(vertices);
		boss->setNormals(normals);
		boss->setTexCoords(texCoords);
	}
	boss->clearElements();

	BVector min(-length * 0.5f, -width * 0.5f, -height * 0.5f);
	BVector max(length * 0.5f, width * 0.5f, height * 0.5f);
	BReal dx = length / lengthSegments;
	BReal dy = width / widthSegments;
	BReal dz = height / heightSegments;

	{//flank.
		int count = 0;
		for (int i = 0; i < lengthSegments; i++)
		{
			BReal x = min.x() + dx * i;
			BReal y = min.y();
			(*vertices)[count++] = BVector(x, y, min.z());
		}
		for (int i = 0; i < widthSegments; i++)
		{
			BReal x = max.x();
			BReal y = min.y() + dy * i;
			(*vertices)[count++] = BVector(x, y, min.z());
		}
		for (int i = 0; i < lengthSegments; i++)
		{
			BReal x = max.x() - dx * i;
			BReal y = max.y();
			(*vertices)[count++] = BVector(x, y, min.z());
		}
		for (int i = 0; i < widthSegments; i++)
		{
			BReal x = min.x();
			BReal y = max.y() - dy * i;
			(*vertices)[count++] = BVector(x, y, min.z());
		}
		(*vertices)[count++] = vertices->first();
		for (int i = 0; i <= count; i++)
		{
			float tx = (float)i / count;
			(*texCoords)[i].set(tx, 1.0f);
		}

		float ty_step = 1.0f / heightSegments;
		float ty = 0.0f;
		for (int r = 1; r <= heightSegments; r++)
		{
			int first = columnCount * r;
			BReal z = dz * r;
			ty += ty_step;
			for (int c = 0; c < columnCount; c++)
			{
				const BVector& v = (*vertices)[c];
				const BCoord& co = (*texCoords)[c];
				(*vertices)[first + c].set(v.x(), v.y(), v.z() + z);
				(*texCoords)[first + c].set(co.x(), 1.0f - ty);
			}
		}

		BIntArray* flankIndices = new BIntArray(columnCount * heightSegments * 4);
		BElement* flankPrimitive = new BElement(Primitive_Quads, flankIndices);
		for (int r = 0; r < heightSegments; r++)
		{
			int head = columnCount * r;
			int pos = columnCount * r * 4;
			for (int c = 0; c < columnCount; c++)
			{
				int index0 = head + c;
				int index1 = head + (c + 1) % columnCount;
				int index2 = index0 + columnCount;
				int index3 = index1 + columnCount;
				(*flankIndices)[pos + c * 4] = index0;
				(*flankIndices)[pos + c * 4 + 1] = index1;
				(*flankIndices)[pos + c * 4 + 2] = index3;
				(*flankIndices)[pos + c * 4 + 3] = index2;
			}
		}
		boss->addElement(flankPrimitive);
	}

	int bottomHead = flankNumVerts;
	int topHead = bottomHead + bottomNumVerts;
	{// make bottom and top vertices.

		int row_count = widthSegments + 1;
		int col_count = lengthSegments + 1;
		float tdx = 1.0f / lengthSegments;
		float tdy = 1.0f / widthSegments;
		for (int r = 0; r < row_count; r++)
		{
			BReal x = min.x();
			float tx = 0;
			BReal y = min.y() + r * dy;
			float ty = r * tdy;
			int bottom_pos = bottomHead + r * col_count;
			int top_pos = topHead + r * col_count;
			for (int c = 0; c < col_count; c++)
			{
				(*vertices)[bottom_pos + c].set(x, y, min.z());
				(*texCoords)[bottom_pos + c].set(tx, ty);
				(*vertices)[top_pos + c].set(x, y, max.z());
				(*texCoords)[top_pos + c].set(tx, 1.0f - ty);
				x += dx;
				tx += tdx;
			}
		}
	}

	{// make top quads.
		int row_count = widthSegments + 1;
		int col_count = lengthSegments + 1;
		BIntArray* indices = new BIntArray(lengthSegments * widthSegments * 4);
		for (int r = 0; r < widthSegments; r++)
		{
			int head = topHead + r * col_count;
			int pos = r * lengthSegments * 4;
			for (int c = 0; c < lengthSegments; c++)
			{
				int i0 = head + c;
				int i1 = i0 + 1;
				int i2 = i1 + col_count;
				int i3 = i0 + col_count;
				int index = pos + c * 4;
				(*indices)[index + 0] = i0;
				(*indices)[index + 1] = i1;
				(*indices)[index + 2] = i2;
				(*indices)[index + 3] = i3;
			}
		}
		boss->addElement(Primitive_Quads, indices);
	}

	{// make bottom quads.
		int row_count = widthSegments + 1;
		int col_count = lengthSegments + 1;
		BIntArray* indices = new BIntArray(lengthSegments * widthSegments * 4);
		for (int r = 0; r < widthSegments; r++)
		{
			int head = bottomHead + r * col_count;
			int pos = r * lengthSegments * 4;
			for (int c = 0; c < lengthSegments; c++)
			{
				int i0 = head + c;
				int i1 = i0 + 1;
				int i2 = i1 + col_count;
				int i3 = i0 + col_count;
				int index = pos + c * 4;
				(*indices)[index + 0] = i0;
				(*indices)[index + 1] = i3;
				(*indices)[index + 2] = i2;
				(*indices)[index + 3] = i1;
			}
		}
		boss->addElement(Primitive_Quads, indices);
	}

	boss->smooth();
}
